#!/usr/bin/env python

import sip

class Uri(sip.SIP):
    scheme = 'sip'
    user = ''
    passwd = ''
    host = ''
    port = ''

    #psep = ';'
    #hmark = '?'
    #hsep = ';'
    def __init__(self, *args, **kwargs):
        # TODO change the params from a dict() into a utils.SymbolicList()
        # TODO change the headers from a list() into a utils.SymbolicList()
        self.params = {}
        self.headers = []
        super(Uri, self).__init__(*args, **kwargs)

    def parse(self, buf):
        def extract_scheme(buf):
            l = buf.split(':', 1)
            if len(l) == 2:
                self.scheme = l[0]
                buf = l[1]
            return buf

        def extract_userinfo(buf):
            userpass = None
            l = buf.split('@', 1)
            if len(l) == 2:
                self.user = l[0]
                if ':' in self.user:
                    self.user, self.passwd = self.user.split(':', maxcount=1)
                buf = l[1]
            return buf

        def extract_host(buf):
            import voipy.utils
            buf = voipy.utils.ParsingString(buf)
            ndx = buf.findfirst(";?")
            if ndx == -1:
                self.host = buf
                buf = ""
            else:
                self.host = buf[:ndx]
                buf = buf[ndx+1:]

                if ':' in self.host:
                    self.host, self.port = self.host.split(':', maxcount=1)
                    self.port = long(self.port)
            return buf

        def extract_params(buf):
            # FIXME clobbers
            if not len(buf) or buf[0] != ';':
                return buf
            ndx = buf.find('?')
            if ndx == -1:
                buf = ""
            else:
                plist = buf[:ndx]
                buf = buf[ndx:]

            for p in [s for s in plist.split(';') if s.strip()]:
                pn, pv = s.split('=', maxcount=1)
                self.params[pn] = pv
            return buf

        def extract_headers(buf):
            # FIXME clobbers
            if not len(buf) or buf[0] != '?':
                return buf
            for hdr in buf[1:].split('&'):
                hn, hv = hdr.split('=', maxcount=1)
                self.headers[hn] = hv
            return ""

        buf = extract_scheme(buf)
        buf = extract_userinfo(buf)
        buf = extract_host(buf)
        buf = extract_params(buf)
        buf = extract_headers(buf)

    def __str__(self):
        def pack_user():
            if self.user or self.passwd:
                s = self.user
                if self.passwd:
                    s += ':' + self.passwd
                return s + '@'
            return ''
        def pack_host():
            if self.port:
                return self.host + ':' + str(self.port())
            return self.host
        def _dump_dict(d, s):
            return s.join([ v and '%s=%s'%(k,v) or k+'='
                    for k,v in d.iteritems()
                ])
        def pack_params():
            # FIXME use a user adjustable ';' -> self.psep ??
            if self.params:
                return ';' + _dump_dict(self.params, ';')
            return ''
        def pack_headers():
            if self.headers:
                return '?' + _dump_dict(self.headers, '&')
            return ''

        return '%s:%s%s%s%s'%(self.scheme, pack_user(), pack_host(),
                pack_params(), pack_headers())
